#!/usr/bin/python
# -*- coding: utf-8 -*-

#-------------------------------------------------
#Create At: 2008-6-21 上午06:14:44 
#Create By: Fla.sam
#
#DESC: google app blog 
#
#-------------------------------------------------

from blog import models
from blog import blog_forms
from django.core.context_processors import request
from django.http import HttpResponse, HttpResponseRedirect
from django.newforms import forms, fields
from django.template import Context, loader
from google.appengine.api import users
from google.appengine.ext import db
from django.newforms import forms
import logging

def _user_info(request):

    #get user
    try:
        user = users.get_current_user()
    except users.UserNotFoundError:
        pass
    
    # check user is login or logout, set user infomations
    if user:
        user_login_logout_url = users.create_logout_url( "/blog/" )
        user_login_logout_name = 'Logout'
        user_name = user.nickname()
        is_logined = True
        is_admin = users.is_current_user_admin()
    else:
        user_login_logout_url = users.create_login_url( '/blog/' )
        user_login_logout_name = 'Login'
        user_name = ''
        is_logined = False
        is_admin = False
        
    return user, user_name, is_logined, is_admin, user_login_logout_name, user_login_logout_url


def index( request ):

    #load template
    index_template = loader.get_template( 'index.html' )
    
    user, user_name, is_logined, is_admin, user_login_logout_name, user_login_logout_url = \
        _user_info(request)
        
    # get link list
    link_lists = models.Link.all()
    link_lists.order( 'link_name' )

    # get article list, only admin can view all article
    if is_admin:
        article_lists = models.Article.all().order( '-article_datetime' ).fetch( 10 )
    else:
        article_lists = models.Article.all().filter( 'article_publiced = ', True ).order( '-article_datetime' ).fetch( 10 )
        
    #get all tag
    all_tags = models.Tag.all()

    index_context = Context( {'user_login_logout_url': user_login_logout_url, \
                             'user_login_logout_name': user_login_logout_name, \
                             'user_name': user_name, \
                             'is_admin': is_admin, \
                             'is_logined':is_logined, \
                             'link_lists':link_lists, \
                             'article_lists':article_lists, \
                             'tag_lists': all_tags
                              } )

    return HttpResponse( index_template.render( index_context ) )

def url_link_quick_add( request ):
    '''
    quick add a url link , no tag set
    @param request:
    '''
    
    user, user_name, is_logined, is_admin, user_login_logout_name, user_login_logout_url = \
        _user_info(request)
    
    # check is admin    
    if not is_admin:
        return HttpResponseRedirect( '/blog/' )
    
    # check http mothod
    if request.method == 'GET':
        redirect_template = loader.get_template( 'redirect.html' )
        info = u'Not Allow GET mothod'
        redirect_to = '/blog/'
        redirect_context =  Context( {'info':info, \
                                       'redirect_to':redirect_to} )
        return HttpResponse( redirect_template.render( redirect_context ) )
    elif request.method == 'POST':
        _name = request.POST.get( 'name', None )
        _url = request.POST.get( 'link', None )
    
        #TODO: should check input value ?
        try:
            link_instance = models.Link( link_name=_name, link_url=_url )
        except db.BadValueError:
            redirect_template = loader.get_template( 'redirect.html' )
            info = u'Bad Input Value'
            redirect_to = '/blog/'
            redirect_context =  Context( {'info':info, \
                                         'redirect_to':redirect_to} )
            return HttpResponse( redirect_template.render( redirect_context ) )
        link_instance.put()

    return HttpResponseRedirect( '/blog/' )

def url_link_del( request, key ):
    user, user_name, is_logined, is_admin, user_login_logout_name, user_login_logout_url = \
        _user_info(request)
    
    # check is admin    
    if not is_admin:
        return HttpResponseRedirect( '/blog/' )
    
    if request.method == 'GET':
        #_link = db.GqlQuery('SELECT * FROM Link WHERE id = :id', id=id)
        try:
            _link = models.Link.get( key )
            _link.delete()
        except db.BadKeyError:
            return HttpResponseRedirect( '/blog/' )
    elif request.method == 'POST':
        pass
    else:
        pass
    
    return HttpResponseRedirect( '/blog/' )

def add_new_article( request ):
    
    user, user_name, is_logined, is_admin, user_login_logout_name, user_login_logout_url = \
        _user_info(request)
        
    if not is_admin:
        return HttpResponseRedirect('/blog/')
    
    new_article_template = loader.get_template( 'add_article.html' )
    
    # check http mothod
    if request.method =='GET':
        # just return add article form , let uesr add new article
        new_article_context = Context( {'user_login_logout_url': user_login_logout_url, \
                             'user_login_logout_name': user_login_logout_name, \
                             'user_name': user_name, \
                             'is_admin': is_admin, \
                             'is_logined':is_logined, \
                              } )
    
        return HttpResponse( new_article_template.render( new_article_context ) )
    elif request.method == 'POST':
        # ok user post new article, let me check input value
        _title = request.POST.get( 'title', '' )
        _content = request.POST.get( 'content', '' )
        _public = request.POST.get( 'public', False )
        _tag = request.POST.get( 'tag', '' )
        
        #check public
        if _public:
            _public = True
        
        #check tag
        _t = []
        if _tag == '':
            _t.append( 'Untaged' )
        else:   
            _tag = _tag.split( ',' )
            for x in _tag:
                _t.append( x.strip().capitalize() )
        _tag = _t
        
        #check tag tabel
        _tag_instance_list = []
        for _tag_name in _tag:
            _t = models.Tag.gql( 'WHERE tag_name = :name', name=_tag_name )
            if _t.count() == 0:
                _t = models.Tag( tag_name=_tag_name, tag_rating=1 )
                _t.put()
                _tag_instance_list.append( _t )
            elif _t.count() == 1:
                _t = _t.get()
                _t.tag_rating += 1
                _t.put()
                _tag_instance_list.append( _t )
            else:
                pass

        # ok insert into database
        article_instance = models.Article( article_title=_title, \
                                          article_content=_content, \
                                          article_publiced=_public, \
                                          article_submit_user=user, \
                                          article_rating=50, \
                                          article_hit=1 )
        
        #set article's tags
        for x in _tag_instance_list:
            article_instance.article_tags.append( x.key() )
            
        article_instance.put()
        
        # should add form preview   
        return HttpResponseRedirect( '/blog/' )
        
    else:
        # oops ? what's wrong, not get or post method
        return HttpResponseRedirect( '/blog/' )
    
def del_article_by_key( request, key ):
    
    user, user_name, is_logined, is_admin, user_login_logout_name, user_login_logout_url = \
        _user_info(request)
    
    # check is admin    
    if not is_admin:
        return HttpResponseRedirect( '/blog/' )
    
    if request.method == 'GET':
        #_link = db.GqlQuery('SELECT * FROM Link WHERE id = :id', id=id)
        try:
            _article = models.Article.get( key )
            
            _article_tags = _article.article_tags
            
            # clean tag_rating < 1 
            for x in _article_tags:
                _tag = models.Tag.get( x )
                _tag.tag_rating -= 1 
                if _tag.tag_rating < 1:
                    _tag.delete()
                else:
                    _tag.put()
            _article.delete()
        except db.BadKeyError:
            return HttpResponseRedirect( '/blog/' )
    elif request.method == 'POST':
        pass
    else:
        pass
    
    return HttpResponseRedirect( '/blog/' )

def edit_article_by_key( request, key ):
    
    user, user_name, is_logined, is_admin, user_login_logout_name, user_login_logout_url = \
        _user_info(request)
        
    if not is_admin:
        return HttpResponseRedirect('/blog/')
    
    if request.method == 'GET':
        #just read article info, make form,show to user
        try:
            _article = models.Article.get( key )
        except db.BadKeyError:
            return HttpResponseRedirect( '/blog/article/add/' )
        
        _tags = []
        for x in _article.article_tags:
            _t = models.Tag.get( x )
            _tags.append( _t.tag_name )
            
        _tags = ', '.join( _tags )

        edit_article_template = loader.get_template( 'edit_article.html' )
    
        article_context = Context( { 'user_login_logout_url': user_login_logout_url, \
                             'user_login_logout_name': user_login_logout_name, \
                             'user_name': user_name, \
                             'is_admin': is_admin, \
                             'is_logined':is_logined, \
                             'article': _article, \
                             'article_tags': _tags
                             } )
        
        return HttpResponse( edit_article_template.render( article_context ) )
                
    elif request.method == 'POST':

        # ok user post article form , let me check input value
        _title = request.POST.get( 'title', '' )
        _content = request.POST.get( 'content', '' )
        _public = request.POST.get( 'public', False )
        _tag = request.POST.get( 'tag', '' )
        _key = request.POST.get( 'key' )
        
        #check public
        if _public:
            _public = True
        
        #check tag
        _t = []
        if _tag == '':
            _t.append( 'Untaged' )
        else:   
            _tag = _tag.split( ',' )
            for x in _tag:
                _t.append( x.strip().capitalize() )
        _tag = _t
        
        #get old article item
        try:
            _old_article_instance = models.Article.get( _key )
        except db.BadKeyError:
            # not found article by key , redirect to add article form
            HttpResponseRedirect( '/blog/article/add/' )
        
        _old_article_instance.article_title = _title
        _old_article_instance.article_content = _content
        _old_article_instance.article_publiced = _public
          
        #check old tag and new tag
        _new_tag_instances_dict = {}
        for _tag_name in _tag:
            _t = models.Tag.gql( 'WHERE tag_name = :name', name=_tag_name )
            if _t.count() == 0:
                _t = models.Tag( tag_name=_tag_name, tag_rating=0 )
                _t.put()
                _new_tag_instances_dict[_tag_name] = _t
            elif _t.count() == 1:
                _t = _t.get()
                _new_tag_instances_dict[_tag_name] = _t
            else:
                pass
            
        _old_tag_instances_dict = {}
        for x in _old_article_instance.article_tags:
            _t = models.Tag.get( x )
            _old_tag_instances_dict[_t.tag_name] = _t
            
        _all_key = list( set( _new_tag_instances_dict.keys() )|set( _old_tag_instances_dict.keys() ) )
        _need_del_tag_list = list( set( _all_key )^set( _new_tag_instances_dict.keys() ) )
        _need_add_tag_list = list( set( _all_key )^set( _old_tag_instances_dict.keys() ) )
            
        _all_instances_dict = _new_tag_instances_dict.copy()
        _all_instances_dict.update( _old_tag_instances_dict )
        
        # del old key
        for x in _need_del_tag_list:
            #del key string from article.article_tags
            del _old_article_instance.article_tags[_old_article_instance.article_tags.index( _old_tag_instances_dict[x].key() )]
            #update Tag.tag_rating
            _old_tag_instances_dict[x].tag_rating -= 1
            if _old_tag_instances_dict[x].tag_rating < 1:
                _old_tag_instances_dict[x].delete()
            else:
                _old_tag_instances_dict[x].put()
            
        # add new key
        for x in _need_add_tag_list:
            _old_article_instance.article_tags.append( _new_tag_instances_dict[x].key() )
            _new_tag_instances_dict[x].tag_rating += 1
            _new_tag_instances_dict[x].put()
            
        # OK put all into database
        _old_article_instance.put()
        return HttpResponseRedirect( '/blog/' )
                
    else:
        return HttpResponseRedirect( '/blog/article/%s/' % key )

#class ArticleRatingForm(forms.Form):
#    good_article_choice = fields.BooleanField(label='Rating for good article' )
#    bad_article_choice = fields.BooleanField(label='Rating for bad article')
    
def view_article_by_key( request, key ):
    '''
    article view
    @param request:
    @param key:
    '''

    user, user_name, is_logined, is_admin, user_login_logout_name, user_login_logout_url = \
        _user_info(request)
        
    if not is_admin:
        return HttpResponseRedirect('/blog/')
    
    if request.method =='GET':
        try:
            _article_instance = models.Article.get( key )
        except db.BadKeyError:
            return HttpResponseRedirect( '/blog/' )
 
        view_article_template = loader.get_template( 'view_article.html' )
    
        article_context = Context( { 'user_login_logout_url': user_login_logout_url, \
                             'user_login_logout_name': user_login_logout_name, \
                             'user_name': user_name, \
                             'is_admin': is_admin, \
                             'is_logined':is_logined, \
                             'article': _article_instance, \
                             } )
        
        #TODO: update article hit
        #TODO: allow user rating this article
        return HttpResponse( view_article_template.render( article_context ) )
    else:
        return HttpResponseRedirect( '/blog/' )
    
def blog_site_admin(request):
    
    site_admin_template = loader.get_template('site_admin.html')
    
    user, user_name, is_logined, is_admin, user_login_logout_name, user_login_logout_url = \
        _user_info(request)
    
    if request.method == 'GET':
        site_admin_form = blog_forms.SiteAdminForm()
        
        site_admin_context = Context( { 'user_login_logout_url': user_login_logout_url, \
                             'user_login_logout_name': user_login_logout_name, \
                             'user_name': user_name, \
                             'is_admin': is_admin, \
                             'is_logined':is_logined, \
                             'site_admin_form': site_admin_form, \
                             } )
        
        return HttpResponse(site_admin_template.render(site_admin_context))
